# Copyright (C) 2021 Max Schulze. All Rights Reserved. # Modified by Kenvix <i@kenvix.com> @ 2023/9/15 # Modified by CorneliaMo <SweetCorneliaMo@163.com> @ 2026/3/9 # # near-literal Translation of the linux version by Jason A. Donenfeld # to decrypt the dpapi Credentials, you have to be the same user as the wireguard tunnel service, i.e. "nt authority\system", check with "whoami" # this script might be called by task scheduler as # powershell -NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -Command ./WireGuard-Reresolve.ps1 -LoopRunAsCron -DelaySeconds 600 # if you want to try it in cmd, remember to elevate the user, i.e. with psexec from sysutils # psexec -s -i powershell -NoPr... #Requires -RunAsAdministrator param( [switch]$LoopRunAsCron = $false, [int]$DelaySeconds = 600, # Optional: specify DNS server address for Resolve-DnsName. If not set, use system default DNS. [string]$DnsServer = $null, # Optional: prefer AAAA record first (IPv6). Default is prefer A first (IPv4). [switch]$PreferAAAA = $false ) Set-StrictMode-Version3 Add-Type-AssemblyName System.Security functionWireGuard-Reresolve { param( [Parameter(Mandatory = $true)] [string]$File ) Set-Variable CONFIG_FILE -Value$File.ToString().Trim('"') Write-Host"Loading $CONFIG_FILE" if (-not (Test-Path-Path$CONFIG_FILE)) { throwNew-Object System.IO.FileNotFoundException("Wireguard Config $CONFIG_FILE File not found.", $CONFIG_FILE) } $byteCrypted = ((Get-Content-LiteralPath$CONFIG_FILE-Encoding Byte -ReadCount0)) $config = [System.Security.Cryptography.ProtectedData]::Unprotect($byteCrypted, $null, [System.Security.Cryptography.DataProtectionScope]::LocalMachine) $config = [System.Text.UTF8Encoding]::UTF8.GetString($config) Set-Variable Interface -Option Constant -Value$(if ($CONFIG_FILE-match'.?([a-zA-Z0-9_=+.-]{1,64})\.conf.dpapi$') { $matches[1] } else { $null }) functionresolve_endpoint_ip() { param( [Parameter(Mandatory = $true)][string]$Endpoint ) # Endpoint format examples: # example.com:51820 # 1.2.3.4:51820 # [2001:db8::1]:51820 Write-Host"Resolving $Endpoint" $hostAddress = $null $port = $null if ($Endpoint-match'^\[([^\]]+)\]:(\d+)$') { # IPv6 literal return$Endpoint } elseif ($Endpoint-match'^([^:]+):(\d+)$') { $hostAddress = $matches[1] $port = $matches[2] } else { return$Endpoint }
# If hostAddress is already an IP literal, keep as-is. if ($hostAddress-match'^\d{1,3}(\.\d{1,3}){3}$'-or$hostAddress-match'^[0-9a-fA-F:]+$') { return$Endpoint }
# Build Resolve-DnsName base parameters, add -Server only if user specified -DnsServer $dnsArgsBase = @{ Name = $hostAddress DnsOnly = $true ErrorAction = 'Stop' NoHostsFile = $true } if ($DnsServer-and$DnsServer.Trim().Length -gt0) { $dnsArgsBase.Server = $DnsServer.Trim() }
# Resolve domain to IP. Default: prefer A (IPv4). If -PreferAAAA is set: prefer AAAA (IPv6). $types = if ($PreferAAAA) { @('AAAA', 'A') } else { @('A', 'AAAA') }